/*
 * plio.h
 *
 *  Created on: May 2, 2017
 *      Author: yuanjianen
 */

#ifndef _PLIO_H_
#define _PLIO_H_

#include "typedef.h"

#define PORT_Pn_BASE_ADDR				(0xFFF00)

#define plio_read_pin(port,pin)			(((*((uint8 *)(PORT_Pn_BASE_ADDR + (port) * 1))) >> (pin)) & 0x01)
#define plio_write_pin(port,pin,value)	\
				(	((value) == 0) ? 	\
						((*((uint8 *)(PORT_Pn_BASE_ADDR + (port) * 1))) &= ~( 0x01 << (pin)))			\
					: 					\
						((*((uint8 *)(PORT_Pn_BASE_ADDR + (port) * 1))) |= ( 0x01 << (pin)))		\
				)						\

#define INVALID_PORT (0xFFU)
#define INVALID_PIN  (0xFFU)

#define ZERO_INPUT_CONFIG()    {INVALID_PORT,  INVALID_PIN,  FALSE,  FALSE, HOLD_ON_NONE,  0U}
#define ZERO_OUTPUT_CONFIG()   {INVALID_PORT,  INVALID_PIN, OUTPUT_LEVEL_NONE, OUTPUT_LEVEL_NONE}

#define plio_read_input_raw(funid)					(plio_input_switch_data[funid].input_raw)
#define plio_read_input_debounced(funid)			(plio_input_switch_data[funid].input_debounced)
#define plio_read_input_hold(funid)					(plio_input_switch_data[funid].input_hold)


#define plio_read_output_raw(funid)					(drio_read_pin_runtime(plio_output_switch_config[funid].port, plio_output_switch_config[funid].pin))
#define plio_write_output_switch(funid, value)		drio_write_pin_runtime(plio_output_switch_config[funid].port, plio_output_switch_config[funid].pin, value)

#define plio_toggle_output_switch(funid)			drio_toggle_pin_runtime(plio_output_switch_config[funid].port, plio_output_switch_config[funid].pin)

#define plio_get_input_capture_period()				plio_input_pwm.input_captured_pwm_period
#define plio_get_input_capture_duty()				plio_input_pwm.input_captured_pwm_duty

extern void plio_input_switch_sample_task(void);

void plio_init_io(void);
void plio_enter_sleep(void);

typedef struct {
	bool input_raw;
	bool input_debounced;
	uint16 hold_time;
	bool input_hold;
	bool unused;
} PlioInputData;

typedef enum {
	HOLD_ON_NONE = 0x00U,
	HOLD_ON_HIGH,
	HOLD_ON_LOW,
	HOLD_ON_BOTH
} PlioHoldeMode;

typedef enum {
	PULL_DISABLED = 0x00U,
	PULL_UP,
	PULL_DOWN
} PlioPullMode;

typedef enum {
	IO_INTERRUPT_NONE = 0x00U,
	IO_INTERRUPT_NORMAL,
	IO_INTERRUPT_WAKEUP /*This IO is used to wakeup the MCU, it will be disabled at poweron, and will be enabled when going to sleep*/
} PlioInterruptType;

typedef enum {
	OUTPUT_LEVEL_LOW = 0x00U,
	OUTPUT_LEVEL_HIGH,
	OUTPUT_LEVEL_KEEP,

	OUTPUT_LEVEL_KEEP_DEFAULT_LOW,
	OUTPUT_LEVEL_KEEP_DEFAULT_HIGH,
	OUTPUT_LEVEL_NONE
} PlioOutputLevel;



typedef struct {
	uint8 port;
	uint8 pin;

	bool  negative;
	bool  hidrive;

	PlioHoldeMode hold_mode; /*refer enum of PlioHoldeMode*/
	/*The signal that hold for the specified time*/
	uint16 hold_time; /*a unit of ms*/
} PlioInputConfig;



typedef struct {
	uint8 port;
	uint8 pin;

	uint8 poweron_output_level;
	uint8 sleep_output_level;
} PlioOutputConfig;


extern const PlioInputConfig  plio_input_switch_config[];
extern const uint8 plio_input_switch_count;
extern PlioInputData plio_input_switch_data[];

extern const PlioOutputConfig plio_output_switch_config[];
extern const uint8 plio_output_switch_count;



#endif /* _PLIO_H_ */
